#include "CPropertyEditor.h"
#include <stdexcept>
#include <memory>

//-------------------------------------

CPropertyEditor::CPropertyEditor( QWidget *parent )
    : QTableWidget( parent ),
      updateInProgress( false )
{
    setColumnCount( 2 );
    setRowCount( 0 );
    setHorizontalHeaderLabels( QStringList() << "Name" << "Value" );
    setMinimumSize( QSize( 10, 10 ) );
    Clear();
}

//-------------------------------------

void CPropertyEditor::Clear()
{
    for( int i = rowCount(); i >= 0; i-- )
        removeRow( i );
    items.clear();
    groups.clear();
    props.clear();
}

//-------------------------------------

void CPropertyEditor::AddProperty( const QString & group, CPropertyItem * p )
{
    CGroupItem * g = GetGroup( group );
    if( !g )
    {
        g = new CGroupItem( this, group );
        groups.insert(g);
    }
    g->AddItem( p );
}

//-------------------------------------

void CPropertyEditor::DeleteProperty( const QString & group, const QString& key )
{
    if( CGroupItem * g = GetGroup( group ) )
        g->DeleteItem( key );
}

//-------------------------------------

void CPropertyEditor::AddPropRef( CPropertyItem * p )
{
    if( !props.insert( p ).second )
        throw std::runtime_error( "CPropertyEditor::AddPropRef() : Property already present and can not be created!" );
}

//-------------------------------------

void CPropertyEditor::RemovePropRef( CPropertyItem * p )
{
    props.erase( p );
}

//-------------------------------------

void CPropertyEditor::FillTable()
{
    std::vector< CPropertyEditorItem* >::iterator i = items.begin();
    for ( int row = 0; i != items.end(); ++i, ++row )
    {
        CPropertyItem * pri = dynamic_cast<CPropertyItem*>(*i);
        if( !pri )
            continue;

        for ( int col = 0; col < 2; ++col )
        {
            QTableWidgetItem * ptwi;
            if( col == 0 )
            {
                QString key = pri->GetKey();
                ptwi = new QTableWidgetItem( key );
                ptwi->setFlags( ptwi->flags() & ~Qt::ItemIsEditable );
            }
            else
            {
                QString val = pri->GetValue();
                ptwi = new QTableWidgetItem( val );
            }

            setItem( row, col, ptwi );
        }
    }
}

//-------------------------------------

void CPropertyEditor::Update()
{
    if( updateInProgress )
        return;
    updateInProgress = true;

    typedef std::set< CGroupItem*, LessGroupItem >::iterator Iter;
    items.clear();
    for( Iter i( groups.begin() ), last( groups.end() ); i!=last; ++i )
        (*i)->Map( items );
    setRowCount( items.size() );
    FillTable();

    updateInProgress = false;
}

//-------------------------------------

CGroupItem * CPropertyEditor::GetGroupOrCreate( const QString& str )
{
    std::auto_ptr<CGroupItem> g( new CGroupItem( 0, str ) );
    typedef std::set< CGroupItem*, LessGroupItem >::iterator Iter;
    Iter i ( groups.find(g.get()) );
    if( i == groups.end() )
        return CreateGroup( str );
    return (*i);
}

//-------------------------------------

CGroupItem * CPropertyEditor::CreateGroup( const QString& str )
{
    std::auto_ptr<CGroupItem> g( new CGroupItem( this, str ) );
    if( !groups.insert( g.get() ).second )
        throw std::runtime_error( "CPropertyEditor::CreateGroup() : Group already present and can not be created!" );
    Update();
    return g.release();
}

//-------------------------------------

CPropertyItem * CPropertyEditor::GetProperty( const QString & str )
{
    std::auto_ptr<CPropertyItem> item( new CPropertyItem( str, "" ) );
    typedef std::set< CPropertyItem*, LessPropItem >::iterator Iter;
    Iter i ( props.find(item.get()) );
    if( i == props.end() )
        return 0;
    return (*i);
}

//-------------------------------------

CPropertyItem * CPropertyEditor::GetProperty( const QString & group, const QString & key )
{
  if( CGroupItem * g = GetGroup( group ) )
    return g->GetItem( key );
  return 0;
}

//-------------------------------------

CGroupItem * CPropertyEditor::GetGroup( const QString& str )
{
    std::auto_ptr<CGroupItem> g( new CGroupItem( 0, str ) );
    typedef std::set< CGroupItem*, LessGroupItem >::iterator Iter;
    Iter i ( groups.find(g.get()) );
    if( i == groups.end() )
        return 0;
    return (*i);
}
